package org.thingsboard.server.service.schedule;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.async.DeferredResult;
import org.thingsboard.rule.engine.api.RpcError;
import org.thingsboard.server.common.data.SchedulerEvent;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.query.EntityData;
import org.thingsboard.server.common.data.query.EntityDataQuery;
import org.thingsboard.server.common.data.rpc.ToDeviceRpcRequestBody;
import org.thingsboard.server.common.msg.rpc.ToDeviceRpcRequest;
import org.thingsboard.server.dao.entity.EntityQueryDao;
import org.thingsboard.server.service.rpc.FromDeviceRpcResponse;
import org.thingsboard.server.service.rpc.LocalRequestMetaData;
import org.thingsboard.server.service.rpc.TbCoreDeviceRpcService;
import org.thingsboard.server.service.security.AccessValidator;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.UUID;

@Service
@Slf4j
public class DefaultScheduleService implements ScheduleService {

  private static final ObjectMapper jsonMapper = new ObjectMapper();
    @Autowired
    private TbCoreDeviceRpcService deviceRpcService;

    @Autowired
    private EntityQueryDao entityQueryDao;

    @Value("${server.rest.server_side_rpc.min_timeout:5000}")
    private long minTimeout;

    @Value("${server.rest.server_side_rpc.default_timeout:10000}")
    private long defaultTimeout;

    public static final String ENTITY_ALIASES = "entityAliases";
    public static final String METHOD_KEY = "method";
    public static final String CMD_KEY = "cmd";
    public static final String FILTER_KEY = "filter";

    @Override
    public void executeHandler(SchedulerEvent schedulerEvent) {
        switch (schedulerEvent.getType()) {
            case DEFAULT:
                executeDeviceRpcWork(schedulerEvent);
                break;
            default:
        }
    }

    private void executeDeviceRpcWork(SchedulerEvent schedulerEvent) {
     //   log.warn("执行任务[{}]", schedulerEvent);
        JsonNode configuration = schedulerEvent.getConfiguration();
        long expTime = System.currentTimeMillis() + Math.max(minTimeout, defaultTimeout);
        if (configuration != null && configuration.has(ENTITY_ALIASES)) {
            JsonNode entityAliases = configuration.get(ENTITY_ALIASES);
            entityAliases.fields().forEachRemaining(entry -> {
                String method = entry.getValue().get(METHOD_KEY).asText().trim();
                String cmd = entry.getValue().get(CMD_KEY).asText().trim();
                if (StringUtils.isEmpty(method) || StringUtils.isEmpty(cmd))
                    return;
                JsonNode filter = entry.getValue().get(FILTER_KEY);
                List<DeviceId> deviceIds = getDeviceIds(filter);
                deviceIds.forEach(deviceId -> {
                    ToDeviceRpcRequestBody body = new ToDeviceRpcRequestBody(method, cmd);
                    ToDeviceRpcRequest rpcRequest = new ToDeviceRpcRequest(UUID.randomUUID(),
                            schedulerEvent.getTenantId(),
                            deviceId,
                            true,
                            expTime,
                            body
                    );
                    deviceRpcService.processRestApiRpcRequest(rpcRequest, fromDeviceRpcResponse -> {
                     //   log.warn("发送RPC调用");
                     //   log.warn("[{}]", fromDeviceRpcResponse);
                    });
                });

            });
        }
    }
   private final static   String json=" {\"entityFilter\":{},\"pageLink\":{\"pageSize\":1024,\"page\":0,\"sortOrder\":{\"key\":{\"type\":\"ENTITY_FIELD\",\"key\":\"createdTime\"},\"direction\":\"DESC\"}},   \"entityFields\":[],\"latestValues\":[] }";

    private List<DeviceId> getDeviceIds(JsonNode filter) {
        List<DeviceId> deviceIds = new ArrayList<>();
        String type = filter.get("type").asText();
        if (type.equals("singleEntity")) {
            JsonNode singleEntity = filter.get("singleEntity");
            if (singleEntity.get("entityType").asText().equals("DEVICE")) {
                UUID id = UUID.fromString(singleEntity.get("id").asText());
                deviceIds.add(new DeviceId(id));
            }
        } else if (type.equals("entityList")) {
            if ("DEVICE".equals(filter.get("entityType").asText())) {
                try {
                    List<String> ids= jsonMapper.readValue(filter.get("entityList").toString(), ArrayList.class);
                   if(ids!=null){
                       ids.forEach(id->{
                           deviceIds.add(new DeviceId(UUID.fromString(id)));
                       });
                   }
                } catch (JsonProcessingException e) {
                    e.printStackTrace();
                }

            }
        } else if (type.equals("entityName")||type.equals("deviceType")) {
            try {
                ObjectNode  jsonQuery = (ObjectNode) jsonMapper.readTree(json);
                jsonQuery.set("entityFilter",filter);
                EntityDataQuery query= jsonMapper.readValue(jsonQuery.toString(), EntityDataQuery.class);
                List<EntityData> entityList= entityQueryDao.findEntityByQuery(query).getData();
                if(entityList!=null){
                    entityList.forEach(entityData -> {
                        deviceIds.add((DeviceId) entityData.getEntityId());
                    });
                }
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }

        }
        return deviceIds;
    }

//    void executeWork(SchedulerEvent schedulerEvent) {
//        if(schedulerEvent.getConfiguration().has("entityAliases")){
//            JsonNode nodes=schedulerEvent.getConfiguration().get("entityAliases");
//            nodes.forEach((JsonNode node)->{
//                try {
//                    ObjectNode jsonQuery= (ObjectNode) jsonMapper.readTree(json);
//                    jsonQuery.set("entityFilter",node.get("filter"));
//                    EntityDataQuery query= jsonMapper.readValue(jsonQuery.toString(), EntityDataQuery.class);
//                    EntityQueryDao entityQueryDao=SpringUtil.getBean(EntityQueryDao.class);
//                    PageData<EntityData> pageData= entityQueryDao.findEntityByQuery(query);
//                    log.warn("【{}】",pageData.getData());
//                } catch (JsonProcessingException e) {
//                    e.printStackTrace();
//                }
//            });
//            log.warn("任务名称【{}】",schedulerEvent.getName());
//        }
//    }
}
